package com.ionehe.group.common.file.ex.rest;

import com.ionehe.group.common.file.ex.model.UploadDTO;
import com.ionehe.group.common.file.ex.service.UserFileManageService;
import com.ionehe.group.common.io.Response;
import com.ionehe.group.common.uaa.ex.dto.UserDetailDTO;
import com.ionehe.group.common.uaa.ex.utils.LoginUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 文件服务控制器
 * @author 2022/1/14 <a href="mailto:a@ionehe.com">xiu</a>
 */
@RestController
@RequestMapping("/api/common/file")
@Slf4j
@Api(value = "公共模块-文件相关服务", tags = "公共模块-文件相关服务")
public class CommonFileController {
    @Resource
    private LoginUtils loginUtil;
    @Resource
    private UserFileManageService userFiles;

    @ApiOperation("上传文件")
    @PostMapping(value = "/upload", consumes = "multipart/*", headers = "content-type=multipart/form-data")
    public Response<List<UploadDTO>> upload(MultipartHttpServletRequest request) {
        log.info("CommonFileController[]upload[] upload file ");

        List<File> fileList = new ArrayList<>();

        MultiValueMap<String, MultipartFile> multiFileMap = request.getMultiFileMap();

        multiFileMap.forEach((multiFileName, multiFileList) -> {
            for (MultipartFile file : multiFileList) {
                File toFile = multipartFileToFile(file);
                fileList.add(toFile);
            }
        });

        // 默认使用用户id创建一个唯一文件夹
        Response<UserDetailDTO> userRes = loginUtil.getCurrentUser();
        if (!userRes.success()) {
            return Response.no(userRes.getMessage());
        }

        Long userId = userRes.getData().getUserInfoDTO().getId();

        Response<List<UploadDTO>> upload = userFiles.upload(userId, 0L, fileList);

        fileList.forEach(CommonFileController::delTempFile);

        return upload;
    }

    @ApiOperation("删除文件")
    @PostMapping(value = "/del")
    public Response<Boolean> del(Long id) {
        Response<UserDetailDTO> userRes = loginUtil.getCurrentUser();
        if (!userRes.success()) {
            return Response.no(userRes.getMessage());
        }

        Long userId = userRes.getData().getUserInfoDTO().getId();

        return userFiles.delete(userId, id);
    }

    /**
     * 删除本地临时文件
     */
    private static void delTempFile(File file) {
        if (file != null) {
            try {
                log.info("CommonFileController[]deleteTempFile[]path:{}", file.toPath());
                Files.delete(file.toPath());
            } catch (IOException e) {
                log.warn("CommonFileController[]deleteTempFile[]error! cause:{}", e.getMessage());
            }
        }
    }

    /**
     * MultipartFile 转 File
     */
    private File multipartFileToFile(MultipartFile file) {
        File toFile = null;
        try {
            if (Objects.isNull(file) || file.getSize() <= 0) {
                file = null;
            } else {
                InputStream ins = file.getInputStream();
                toFile = new File(file.getOriginalFilename());
                inputStreamToFile(ins, toFile);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return toFile;
    }

    /**
     * 获取流文件
     */
    private void inputStreamToFile(InputStream ins, File file) {
        OutputStream os = null;
        try {
            os = new FileOutputStream(file);
            int bytesRead = 0;
            byte[] buffer = new byte[8192];
            while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                os.close();
                ins.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
